﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Text.RegularExpressions;
using Microsoft.SharePoint.Administration;

namespace de.rwth.rz.campus.sharepointutils.EMail
{
    /// <remarks>
    /// 
    /// Copyright 2010 RWTH Aachen, CAMPUS Labs
    /// 
    /// Licensed under the Apache License, Version 2.0 (the "License");
    /// you may not use this file except in compliance with the License.
    /// You may obtain a copy of the License at
    ///
    /// http://www.apache.org/licenses/LICENSE-2.0
    ///
    /// Unless required by applicable law or agreed to in writing, software
    /// distributed under the License is distributed on an "AS IS" BASIS,
    /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    /// See the License for the specific language governing permissions and
    /// limitations under the License.
    /// 
    /// </remarks>
    public class EMail
    {
        private MailAddress from = null;
        private List<MailAddress> toList = new List<MailAddress>();
        private List<MailAddress> ccList = new List<MailAddress>();
        private List<MailAddress> bccList = new List<MailAddress>();
        private Boolean isHTML = true;
        private String subject = String.Empty;
        private String message = String.Empty;
        private String smtpServerAddress = String.Empty;
        private int smtpServerPort = 25;
        private MailPriority priority = MailPriority.Normal;

        /// <summary>
        /// The constructor initializes a new mail
        /// </summary>
        public EMail()
        {

        }

        /// <summary>
        /// The priority of the mail
        /// </summary>
        public MailPriority Priority
        {
            get { return priority; }
            set { priority = value; }
        }

        /// <summary>
        /// The sender of the e-mail
        /// </summary>
        public MailAddress From
        {
            get { return from; }
            set { from = value; }
        }

        /// <summary>
        /// The list of mail recievers, listed in the TO-field
        /// </summary>
        public List<MailAddress> ToList
        {
            get { return toList; }
            set { toList = value; }
        }

        /// <summary>
        /// The list of mail recievers, listed in the CC (carbon copy)-field
        /// </summary>
        public List<MailAddress> CCList
        {
            get { return ccList; }
            set { ccList = value; }
        }

        /// <summary>
        /// The list of mail recievers, listed in the BCC (blind carbon copy)-field
        /// </summary>
        public List<MailAddress> BCCList
        {
            get { return bccList; }
            set { bccList = value; }
        }

        /// <summary>
        /// True, if the mail-message is HTML encoded (default)
        /// </summary>
        public Boolean IsHTML
        {
            get { return isHTML; }
            set { isHTML = value; }
        }

        /// <summary>
        /// The subject of the mail
        /// </summary>
        public String Subject
        {
            get { return subject; }
            set { subject = value; }
        }

        /// <summary>
        /// The message of the mail
        /// </summary>
        public String Message
        {
            get { return message; }
            set { message = value; }
        }

        /// <summary>
        /// The IP-Address or FQDN of the SMTP server 
        /// </summary>
        public String SMTPServerAddress
        {
            get { return smtpServerAddress; }
            set { smtpServerAddress = value; }
        }

        /// <summary>
        /// The port number of the SMTP Server, default is 25
        /// </summary>
        public int SMTPServerPort
        {
            get { return smtpServerPort; }
            set { smtpServerPort = value; }
        }  

        /// <summary>
        /// Adds a new person to the recievers at the "TO"-Field
        /// </summary>
        /// <param name="eMailAddress">The e-mail address of the person</param>
        /// <param name="name">The name of the person, could be String.Empty or NULL</param>
        public void AddToReciever(String eMailAddress, String name)
        {
            if (!String.IsNullOrEmpty(eMailAddress))
            {
                if (IsValidEMailAddress(eMailAddress))
                {
                    if (String.IsNullOrEmpty(name))
                    {
                        toList.Add(new MailAddress(eMailAddress));
                    }
                    else
                    {
                        toList.Add(new MailAddress(eMailAddress, name));
                    }
                }
            }
        }

        /// <summary>
        /// Adds a new person to the recievers at the "CC"-Field
        /// </summary>
        /// <param name="eMailAddress">The e-mail address of the person</param>
        /// <param name="name">The name of the person, could be String.Empty or NULL</param>
        public void AddCCReciever(String eMailAddress, String name)
        {
            if (!String.IsNullOrEmpty(eMailAddress))
            {
                if (IsValidEMailAddress(eMailAddress))
                {
                    if (String.IsNullOrEmpty(name))
                    {
                        ccList.Add(new MailAddress(eMailAddress));
                    }
                    else
                    {
                        ccList.Add(new MailAddress(eMailAddress, name));
                    }
                }
            }
        }

        /// <summary>
        /// Adds a new person to the recievers at the "BCC"-Field
        /// </summary>
        /// <param name="eMailAddress">The e-mail address of the person</param>
        /// <param name="name">The name of the person, could be String.Empty or NULL</param>
        public void AddBCCReciever(String eMailAddress, String name)
        {
            if (!String.IsNullOrEmpty(eMailAddress))
            {
                if (IsValidEMailAddress(eMailAddress))
                {
                    if (String.IsNullOrEmpty(name))
                    {
                        bccList.Add(new MailAddress(eMailAddress));
                    }
                    else
                    {
                        bccList.Add(new MailAddress(eMailAddress, name));
                    }
                }
            }
        }

        /// <summary>
        /// Checks, if an e-mail address is valid.
        /// </summary>
        /// <param name="eMailAddress">The e-mail address that should be validated</param>
        /// <returns>TRUE, if the e-mail address is valid, else FALSE</returns>
        public static Boolean IsValidEMailAddress(String eMailAddress)
        {
            if (String.IsNullOrEmpty(eMailAddress))
            {
                return false;
            }
            else
            {
                Regex emailRegEx = new Regex("(?<user>[^@]+)@(?<host>.+)");
                return emailRegEx.Match(eMailAddress).Success;
            }
        }

        /// <summary>
        /// Tries to use the SMTP Server from the SharePoint central administration.
        /// </summary>
        /// <param name="spWebApplicationCollection">The SharePoint webapplication collection</param>
        /// <returns>True, if the SMTP Server could be found</returns>
        /// <example>
        /// <code>
        /// bool isSet = SetSPSMTPServer(SPWebService.ContentService.WebApplications);
        /// </code>
        /// </example>
        public Boolean SetSPSMTPServer(SPWebApplicationCollection spWebApplicationCollection)
        {
            String smtpServerAddress = null;
            SPOutboundMailServiceInstance smtpServer = new SPOutboundMailServiceInstance();
            if (spWebApplicationCollection != null)
            {
                foreach (SPWebApplication spWebApplication in spWebApplicationCollection)
                {
                    smtpServer = spWebApplication.OutboundMailServiceInstance;
                    smtpServerAddress = smtpServer.Server.Address;
                    if (String.IsNullOrEmpty(smtpServerAddress))
                    {
                        continue;
                    }
                    else
                    {
                        this.smtpServerAddress = smtpServerAddress;
                        break;
                    }
                }
            }
            return !String.IsNullOrEmpty(smtpServerAddress);
        }

        /// <summary>
        /// Send the mail via SMTP
        /// </summary>
        /// <exception cref="System.ArgumentNullException"/>
        /// <exception cref="System.ArgumentOutOfRangeException"/>
        /// <exception cref="System.InvalidOperationException"/>
        /// <exception cref="System.ObjectDisposedException"/>
        /// <exception cref="System.Net.Mail.SmtpException"/>
        /// <exception cref="System.Net.Mail.SmtpFailedRecipientsException"/>
        public void SendMail()
        {
            SmtpClient client = new SmtpClient(smtpServerAddress, smtpServerPort);
            MailMessage mm = new MailMessage();
            if (this.from != null)
            {
                mm.From = from;
            }
            foreach (MailAddress ma in toList)
            {
                mm.To.Add(ma);
            }
            foreach (MailAddress ma in ccList)
            {
                mm.CC.Add(ma);
            }
            foreach (MailAddress ma in bccList)
            {
                mm.Bcc.Add(ma);
            }
            mm.Subject = this.subject;
            mm.IsBodyHtml = isHTML;
            mm.Body = this.message;
            mm.Priority = this.priority;
            client.Send(mm);
        }
    }
}
